<template>
  <view
    class="carousel-3d-container"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
    @mousedown="mouseStart"
    @mousemove="mouseMove"
    @mouseup="mouseEnd"
    @mouseleave="mouseEnd"
  >
    <view class="carousel-3d" :style="carouselStyle">
      <view
        v-for="(item, index) in items"
        :key="index"
        class="carousel-item"
        :class="{ 'is-active': index === currentIndex }"
        :style="getItemStyle(index)"
        @click="selectItem(index)"
      >
        <image :src="item.image" mode="aspectFill" />
        <view class="item-title">{{ item.title }}</view>
      </view>
    </view>
    <view class="carousel-controls">
      <view class="control-prev" @click="prev">‹</view>
      <view class="control-next" @click="next">›</view>
    </view>
    <view class="carousel-indicators">
      <view
        v-for="(_, index) in items"
        :key="index"
        :class="['indicator', { active: index === currentIndex }]"
        @click="selectItem(index)"
      ></view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';

interface CarouselItem {
  image: string;
  title: string;
}

const props = withDefaults(defineProps<{
  items: CarouselItem[];
  autoplay?: boolean;
  interval?: number;
  perspective?: number;
  radius?: number;
  spacing?: number;
}>(), {
  autoplay: true,
  interval: 3000,
  perspective: 2200,
  radius: 300,
  spacing: 60
});

const currentIndex = ref(0);
const rotating = ref(false);
let autoplayTimer: number | null = null;
let startX = 0;
let currentX = 0;
let isDragging = false;

const carouselStyle = computed(() => ({
  perspective: `${props.perspective}px`
}));

const getItemStyle = (index: number) => {
  const count = props.items.length;
  // 调整角度计算，增加间距效果
  const angle = (360 / count) * (index - currentIndex.value);
  const z = props.radius;
  const dragOffset = isDragging ? (currentX - startX) * 0.5 : 0;
  
  // 计算相对于当前项的距离，用于调整不同位置项的样式
  const distance = Math.abs(index - currentIndex.value);
  const isNeighbor = distance === 1 || (distance === count - 1 && count > 2);
  
  // 根据距离调整缩放和透明度
  const scale = isNeighbor ? 0.8 : distance === 0 ? 1 : 0.65;
  const opacity = isNeighbor ? 0.85 : distance === 0 ? 1 : 0.4;
  
  return {
    transform: `rotateY(${angle + dragOffset}deg) translateZ(${z}px) scale(${scale})`,
    zIndex: angle === 0 ? 10 : Math.round(8 - Math.abs(angle) / 36),
    opacity,
    filter: distance === 0 ? 'brightness(1) blur(0)' : `brightness(${0.7 + (1 - distance / count) * 0.3}) blur(${distance * 0.8}px)`,
    transition: isDragging ? 'none' : 'all 0.6s cubic-bezier(0.25, 0.1, 0.25, 1)'
  };
};

const next = () => {
  if (rotating.value) return;
  rotating.value = true;
  currentIndex.value = (currentIndex.value + 1) % props.items.length;
  setTimeout(() => {
    rotating.value = false;
  }, 500);
};

const prev = () => {
  if (rotating.value) return;
  rotating.value = true;
  currentIndex.value = (currentIndex.value - 1 + props.items.length) % props.items.length;
  setTimeout(() => {
    rotating.value = false;
  }, 500);
};

const selectItem = (index: number) => {
  if (rotating.value || index === currentIndex.value) return;
  rotating.value = true;
  currentIndex.value = index;
  setTimeout(() => {
    rotating.value = false;
  }, 500);
};

const touchStart = (e: TouchEvent) => {
  if (rotating.value) return;
  startX = e.touches[0].clientX;
  isDragging = true;
  stopAutoplay();
};

const touchMove = (e: TouchEvent) => {
  if (!isDragging) return;
  currentX = e.touches[0].clientX;
};

const touchEnd = () => {
  if (!isDragging) return;
  const threshold = 50;
  const delta = currentX - startX;
  
  if (Math.abs(delta) > threshold) {
    if (delta > 0) {
      prev();
    } else {
      next();
    }
  }
  
  isDragging = false;
  startAutoplay();
};

const mouseStart = (e: MouseEvent) => {
  if (rotating.value) return;
  startX = e.clientX;
  isDragging = true;
  stopAutoplay();
};

const mouseMove = (e: MouseEvent) => {
  if (!isDragging) return;
  currentX = e.clientX;
};

const mouseEnd = () => {
  if (!isDragging) return;
  const threshold = 50;
  const delta = currentX - startX;
  
  if (Math.abs(delta) > threshold) {
    if (delta > 0) {
      prev();
    } else {
      next();
    }
  }
  
  isDragging = false;
  startAutoplay();
};

const startAutoplay = () => {
  if (props.autoplay && !autoplayTimer) {
    autoplayTimer = setInterval(next, props.interval);
  }
};

const stopAutoplay = () => {
  if (autoplayTimer) {
    clearInterval(autoplayTimer);
    autoplayTimer = null;
  }
};

onMounted(() => {
  startAutoplay();
});

onUnmounted(() => {
  stopAutoplay();
});
</script>

<style lang="scss">
.carousel-3d-container {
  position: relative;
  width: 100%;
  height: 400rpx;
  margin: 30rpx 0 20rpx;
  overflow: hidden;
  touch-action: pan-y pinch-zoom;
  user-select: none;
  background: linear-gradient(to bottom, rgba(0,0,0,0.02), rgba(0,0,0,0.05));
  border-radius: 24rpx;
}


.carousel-3d {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  will-change: transform;
}

.carousel-item {
  position: absolute;
  width: 100%;
  height: 90%;
  left: 5%;
  top: 5%;
  cursor: pointer;
  backface-visibility: hidden;
  transform-origin: center;
  transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, opacity, filter;
  
  &.is-active {
    z-index: 10;
  }

  image {
    width: 100%;
    height: 100%;
    border-radius: 16rpx;
    box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.5), 0 8rpx 16rpx rgba(0, 0, 0, 0.3);
    pointer-events: none;
    object-fit: cover;
    transform: translateZ(0);
  }

  .item-title {
    position: absolute;
    bottom: 30rpx;
    left: 30rpx;
    right: 30rpx;
    color: #fff;
    font-size: 32rpx;
    font-weight: 600;
    text-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.8);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    opacity: 0;
    transform: translateY(20rpx);
    transition: all 0.5s ease;
    padding: 16rpx 20rpx;
    background: linear-gradient(to top, rgba(0,0,0,0.6), rgba(0,0,0,0));
    border-radius: 0 0 24rpx 24rpx;
  }

  &.is-active .item-title {
    opacity: 1;
    transform: translateY(0);
  }
}

.carousel-controls {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  display: flex;
  justify-content: space-between;
  padding: 0 30rpx;
  pointer-events: none;
  z-index: 20;

  .control-prev,
  .control-next {
    width: 70rpx;
    height: 70rpx;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 44rpx;
    color: #333;
    pointer-events: auto;
    cursor: pointer;
    transition: all 0.3s ease;
    backdrop-filter: blur(8px);
    box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.25), 0 4rpx 10rpx rgba(0, 0, 0, 0.15);
    opacity: 0.95;

    &:active {
      background: rgba(255, 255, 255, 1);
      transform: scale(0.9);
      opacity: 1;
    }
  }
}

.carousel-indicators {
  position: absolute;
  bottom: 16rpx;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 12rpx;
  z-index: 20;

  .indicator {
    width: 12rpx;
    height: 12rpx;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.5);
    transition: all 0.3s ease;
    cursor: pointer;

    &.active {
      background: #fff;
      transform: scale(1.6);
      box-shadow: 0 0 20rpx rgba(255, 255, 255, 0.8);
    }
  }
}
</style>